package com.demo.nio.thread;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * 负责处理客户端链接
 */
public class BossThread extends Thread {

    private final Selector bossSelector;

    private final Selector workSelector;

    private int port = 8080;


    public BossThread(Selector bossSelector, Selector workSelector) {
        super("server_boss");
        this.bossSelector = bossSelector;
        this.workSelector = workSelector;
    }

    public BossThread(Selector bossSelector, Selector workSelector, int port) {
        super("server_boss");
        this.bossSelector = bossSelector;
        this.workSelector = workSelector;
        this.port = port;
    }

    @Override
    public void run() {
        super.run();

        try {
            // 服务端启动
            ServerSocketChannel listenerChannel = ServerSocketChannel.open();
            listenerChannel.socket().bind(new InetSocketAddress(port));
            listenerChannel.configureBlocking(false);
            listenerChannel.register(bossSelector, SelectionKey.OP_ACCEPT);
            System.out.println("服务器启动成功,端口号是" + port);

            // 监测是否有新的连接，这里的1指的是阻塞的时间为 1ms
            while (true) {

                if (bossSelector.select(1) > 0) {

                    Set<SelectionKey> keySets = bossSelector.selectedKeys();
                    Iterator<SelectionKey> keyIterator = keySets.iterator();

                    while (keyIterator.hasNext()) {
                        SelectionKey key = keyIterator.next();
                        // Tests whether this key's channel is ready to accept a new socket  connection.
                        if (key.isAcceptable()) {
                            try {
                                // 每来一个新连接，不需要创建一个线程，而是直接注册到clientSelector
                                SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept();
                                clientChannel.configureBlocking(false);
                                clientChannel.register(workSelector, SelectionKey.OP_READ);
                                System.out.println("有客户端连接来了: " + clientChannel.getRemoteAddress());
                            } finally {
                                keyIterator.remove();
                            }
                        }
                    }
                }
            }


        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
